home *** CD-ROM | disk | FTP | other *** search
- /******************************************************************************
- * FREXX PROGRAMMING LANGUAGE *
- ******************************************************************************
-
- numexpr.c
-
- Supports *FULL* C language expression operator priority and much more...!
-
- *****************************************************************************/
-
- /************************************************************************
- * *
- * fpl.library - A shared library interpreting script langauge. *
- * Copyright (C) 1992-1994 FrexxWare *
- * Author: Daniel Stenberg *
- * *
- * This program is free software; you may redistribute for non *
- * commercial purposes only. Commercial programs must have a written *
- * permission from the author to use FPL. FPL is *NOT* public domain! *
- * Any provided source code is only for reference and for assurance *
- * that users should be able to compile FPL on any operating system *
- * he/she wants to use it in! *
- * *
- * You may not change, resource, patch files or in any way reverse *
- * engineer anything in the FPL package. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
- * *
- * Daniel Stenberg *
- * Ankdammsgatan 36, 4tr *
- * S-171 43 Solna *
- * Sweden *
- * *
- * FidoNet 2:201/328 email:dast@sth.frontec.se *
- * *
- ************************************************************************/
-
- #ifdef AMIGA
- #include <exec/types.h>
- #include <proto/exec.h>
- #elif defined(UNIX)
- #include <sys/types.h>
- #endif
-
- #include "script.h"
- #include <stdio.h>
- #include <stddef.h>
- #include <limits.h>
-
- static ReturnCode AddUnary(struct Data *, struct Expr *, Operator);
- static ReturnCode Calc(struct Data *, struct Expr *, struct Expr *);
- static void INLINE HandleString(struct Data *, struct Expr *);
- static ReturnCode INLINE GetArrayInfo(struct Data *, long *, long *, long, char *);
- static ReturnCode INLINE Convert(struct Expr *, struct Data *);
- static void Clean(struct Data *, struct Expr *);
- static ReturnCode INLINE CallFunction(struct Data *, struct fplArgument *,
- struct Identifier *);
- static ReturnCode INLINE PrototypeInside(struct Data *,
- struct Expr *val,
- long,
- struct Identifier *);
- static ReturnCode INLINE inside(struct Data *, struct fplArgument *,
- struct Identifier *);
- #ifdef STRING_STACK
- static ReturnCode INLINE StringToStack(struct Data *,
- struct fplStr **);
- static ReturnCode INLINE StringFromStack(struct Data *,
- struct fplStr **);
- #endif
-
- /***********************************************************************
- *
- * int Expression(struct Expr *, struct Data *, char, struct Local *)
- *
- * Returns a nonzero value if any error occured.
- * The result of the Expression is returned in the Expr structure which you
- * give the pointer to in the first argument.
- *
- *****************/
-
- ReturnCode REGARGS
- Expression(struct Expr *val, /* return value struct pointer */
- struct Data *scr, /* everything */
- long control, /* ESPECIALLLY DEFINED */
- struct Identifier *ident) /* pointer to the pointer holding
- the local variable names linked
- list */
- {
- struct Expr *expr, *basexpr;
- ReturnCode ret;
- struct Identifier *pident; /* general purpose struct identifier pointer */
- struct Unary *un; /* general purpose struct Unary pointers */
- long *dims=NULL; /* dimension pointer for variable arrays! */
- long pos; /* general purpose integer */
- char *text; /* general purpose char pointer */
- char hit;
- char *array;
- long num;
- long *nump; /* for general purpose long pointers */
- struct fplMsg *msg;
- struct fplStr *string;
- #if defined(AMIGA) && defined(SHARED)
- if(ret=CheckStack(scr, scr->stack_limit, scr->stack_margin)) {
- if(ret==1)
- return(FPLERR_OUT_OF_MEMORY);
- else
- return(FPLERR_OUT_OF_STACK);
- }
- #endif
-
- GETMEM(expr, sizeof(struct Expr));
- memset(expr, 0, sizeof(struct Expr));
- basexpr=expr;
-
- while (1) {
- if(ret=Eat(scr)) { /* getaway blanks and comments */
- if(control&CON_END && ret==FPLERR_UNEXPECTED_END) {
- /* If there can be an unexpected ending, break out of the loop
- with a nice return code! */
- break;
- }
- } else if(expr->flags&FPL_STRING && !(control&CON_GROUNDLVL))
- /* get outta string calcs if not on ground level! */
- break;
-
- if(!(expr->flags&FPL_OPERAND)) { /* operand coming up */
-
- if(control&CON_IDENT ||
- isident(*scr->text)) {
- /*
- * It's a valid identifier character.
- */
- char *point;
- num=0; /* Dimension counter when taking care of array variables */
-
-
- if(control&CON_IDENT) {
- if(!ident)
- ret=FPLERR_IDENTIFIER_NOT_FOUND;
- control&=~CON_IDENT; /* switch off that bit to get away from any
- trouble such as double using this! */
- } else {
- CALL(Getword(scr));
- ret=GetIdentifier(scr, scr->buf, &ident);
- }
-
- point=scr->text;
- Eat(scr); /* getaway blanks */
-
- /*
- * `ret' can only be FPL_OK or FPLERR_IDENTIFIER_NOT_FOUND at this
- * position.
- */
-
- if(control&CON_DECLARE && *scr->text==CHAR_OPEN_PAREN) {
- CALL(PrototypeInside(scr, val, control, ident));
- expr->flags|=FPL_OPERAND|FPL_ACTION;
-
- } else if(control&CON_DECLARE ||
- (ident && ident->flags&FPL_VARIABLE)) {
- /* The ident check above really must be there, otherwise we might
- read it when it is a NULL pointer" */
-
- /* it's a variable */
- pident=ident;
- if(ret && /* we didn't find it... */
- !(control&CON_DECLARE)) /* and we're not declaring! */
- /*
- * We didn't find the requested identifier and we're *NOT*
- * declaring. This means error!
- */
- return(ret);
- else if(!ret) {
- if(ident->flags&FPL_REFERENCE)
- return FPLERR_ILLEGAL_VARIABLE; /* this is a reference _only_! */
-
- /* The symbol was found */
- if(control&CON_LEVELOK) /* level _is_ OK! */
- ;
- else if(control&CON_DECLARE &&
- (ident->level>=scr->varlevel || scr->varlevel==1)) {
- /*
- * If the name already declared in this (or higher) level
- * and declaration is wanted.
- */
- if((ident->flags&FPL_STATIC_VARIABLE &&
- control&CON_DECLSTATIC &&
- ident->level==scr->varlevel) ||
- /*
- * If this is a `static' variable and the variable already
- * exists on this very level in this very function as static,
- * then skip this. It's perfectly OK to jump to the ending
- * semicolon since this has been parsed before!
- */
-
- (ident->flags&FPL_EXPORT_SYMBOL && control&CON_DECLEXP)) {
-
- /*
- * If this is an `export' symbol and it already exists as an
- * `export' symbol! Then just ignore this!
- */
-
- /*
- * The current implementation unfortunately uses the statement
- * below to pass this declaration. That means comma-
- * separated exported symbols will be passed if only the first
- * is alredy declared... This will although work in all those
- * cases it is the SAME code that is executed twice!
- */
-
-
- if(GetEnd(scr, CHAR_SEMICOLON, 255, FALSE))
- return FPLERR_MISSING_SEMICOLON;
- scr->text--; /* get back on the semicolon! */
- break;
- } else {
- CALL(Warn(scr, FPLERR_IDENTIFIER_USED));
- /* run it over! */
- DelIdentifier(scr, ident->name, NULL);
- }
- } else if(!(control&CON_DECLARE) &&
- (ident->level && /* not global */
- ident->level<(scr->varlevel-scr->level)))
- /*
- * From the wrong program level and we're not declaring.
- */
- return(FPLERR_IDENTIFIER_NOT_FOUND);
- else if(ident->flags&FPL_STATIC_VARIABLE &&
- ((ident->func && (ident->func==scr->func)) ||
- ident->level>scr->varlevel)
- )
- /*
- * A static variable declared either in the wrong function or
- * in a higher level!
- */
- return(FPLERR_IDENTIFIER_NOT_FOUND);
- }
-
- text = NULL; /* no name information yet! */
-
- control &= ~CON_LEVELOK; /* forget about the level OK stuff!! */
-
- if(*scr->text==CHAR_OPEN_BRACKET) {
- /*
- * It's an array. Get the result of the expression within the
- * square brackets.
- */
-
- if(!dims) {
- GETMEM(dims, MAX_DIMS*sizeof(long));
- }
- if(!(control&CON_DECLARE) && pident->data.variable.size)
- num=pident->data.variable.num;
- if(control&CON_DECLARE || num) {
- /*
- * Get the name now, cause the GetArrayInfo() call may
- * destroy the 'scr->buf' buffer!
- */
- STRDUP(text, scr->buf);
-
- GETMEM(nump, sizeof(long));
- *nump = num;
- CALL(GetArrayInfo(scr, dims, nump, control, text));
- num = *nump;
- FREE(nump);
- if(!(control&CON_DECLARE)) {
- /*
- * Free the name now, cause we don't declare anything
- * and this isn't needed any more!
- */
- FREE(text);
- text = NULL;
- }
- if(!(control&CON_DECLARE)) {
- if(num > pident->data.variable.num) {
- /*
- * If not declaring and overfilled quota: fail!
- *
- *
- * Copy the variable name to the buffer to make the
- * error message look good!
- */
- strcpy(scr->buf, pident->name);
- return FPLERR_ILLEGAL_ARRAY;
-
- } else {
- for(pos=0; pos<num; pos++)
- if(pident->data.variable.dims[pos]<=dims[pos]) {
- /*
- * Copy the variable name to the buffer to make the
- * error message look good!
- */
- strcpy(scr->buf, pident->name);
- return FPLERR_ILLEGAL_ARRAY;
- }
- }
- }
- point=scr->text; /* move point to current location */
- Eat(scr); /* pass all traling whitespaces */
- }
- }
- if(control&CON_DECLARE) {
- expr->flags|=FPL_ACTION;
- GETMEM(pident, sizeof(struct Identifier));
-
- pident->level=
- (control&(CON_DECLEXP|CON_DECLGLOB))?0:scr->varlevel;
- pident->flags=
- (control&CON_DECLINT?FPL_INT_VARIABLE:FPL_STRING_VARIABLE)|
- (control&CON_DECLEXP?FPL_EXPORT_SYMBOL:0)|
- (control&CON_DECLGLOB?FPL_GLOBAL_SYMBOL:
- (control&CON_DECLSTATIC?FPL_STATIC_VARIABLE:0))|
- (control&CON_DECL8?FPL_CHAR_VARIABLE:
- (control&CON_DECL16?FPL_SHORT_VARIABLE:0))|
- (control&CON_DECLCONST?FPL_READONLY:0);
-
- pident->file=scr->prog->name; /* file */
-
- pident->func=scr->func; /* declared in this function */
-
- /* Get variable name */
- if(text)
- /*
- * The name has already been allocated above!
- */
- pident->name = text;
- else {
- /*
- * Get the name!
- */
- STRDUP(pident->name, scr->buf); /* no real strdup */
- }
- if(num) {
- /*
- * Array variable declaration! It is a bit different from
- * common variable declaration so I decided to put the code
- * for it right here:
- */
- long size=dims[0]; /* array size */
-
- for(pos=1; pos<num; pos++)
- size*=dims[pos];
-
- /* Now `size' is the total number of members in the array we're
- about to declare */
-
- /* Get memory for the dimension array */
- GETMEM(pident->data.variable.dims, num * sizeof(long));
-
- /* Copy the dim info to the newly allocated area */
- memcpy((void *)pident->data.variable.dims, dims, num*sizeof(long));
-
- /* Get memory for the array */
- GETMEM(pident->data.variable.var.val32, size * sizeof(long));
-
- /* Set all string lengths to NULL and integers to zero: */
- memset(pident->data.variable.var.val32, 0, size * sizeof(void *));
-
- pident->data.variable.size=size; /* total number of array members */
- pident->data.variable.num=num; /* number of dimensions */
-
- /* reset the dims array! */
- memset((void *)dims, 0, sizeof(long) * num);
-
- /* reset num: */
- num=1;
-
- } else {
- #ifdef DEBUG
- CheckMem(scr, pident);
- #endif
-
- GETMEM(pident->data.variable.var.val32, sizeof(long));
- *pident->data.variable.var.val32=0;
- pident->data.variable.num=0;
- pident->data.variable.size=1;
- }
- /*
- * We add the symbol to the local data in all cases except when
- * the symbol is global or static.
- */
- CALL(AddVar(scr, pident,
- control&(CON_DECLGLOB|CON_DECLSTATIC)?
- &scr->globals:&scr->locals));
- }
-
- /*
- * Now when all declarations is done, all assigns are left:
- */
-
- expr->flags|=FPL_OPERAND;
- if (pident->flags&FPL_STRING_VARIABLE) { /* string variable */
- if(*scr->text==CHAR_OPEN_BRACKET) { /* just one character */
- /*
- * Get the result of the expression.
- */
- char *value;
- CALL(Expression(val, (scr->text++, scr),
- CON_GROUNDLVL|CON_NUM, NULL));
- if(*scr->text!=CHAR_CLOSE_BRACKET) {
- CALL(Warn(scr, FPLERR_MISSING_BRACKET));
- /* we can continue anyway! */
- } else
- scr->text++;
-
- CALL(Eat(scr)); /* eat white space */
-
- if(pident->data.variable.num) {
- /* pick out the proper array member */
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- strcpy(scr->buf, pident->name);
- return FPLERR_ILLEGAL_ARRAY; /* we don't know what was meant! */
- }
- } else
- pos=0;
-
- if(&pident->data.variable.var.str[pos] &&
- (val->val.val >= pident->data.variable.var.str[pos]->len)) {
- /* force to zero! */
- val->val.val=0;
- } else if(val->val.val<0) {
- strcpy(scr->buf, pident->name);
- return FPLERR_STRING_INDEX; /* we don't know what was meant! */
- }
-
- /*
- * (I) Here we should be able to operate the character read
- * from the string. ++ and -- should work to enable advanced
- * string modification handling without the
- * overhead of getting the string, changing it and then re-
- * assign it back. This *MUST* be implemented soon cause
- * it's a real killer!
- */
-
- value=(char *)&pident->data.variable.var.str[pos]->string[val->val.val];
-
- if(ASSIGN_OPERATOR) {
- char was=*scr->text;
- long valint=*value;
- if(pident->flags&FPL_READONLY)
- return FPLERR_READONLY_VIOLATE;
- expr->flags|=FPL_ACTION;
- if(*scr->text==CHAR_ASSIGN)
- scr->text++;
- else if(scr->text[2]==CHAR_ASSIGN)
- scr->text+=3;
- else
- scr->text+=2;
- /* single assign */
- CALL(Expression(val, scr, CON_NORMAL|CON_NUM, NULL));
- CALL(CmpAssign(scr, val->val.val, &valint, FPL_CHAR_VARIABLE, was));
- *value=valint;
- }
-
- expr->val.val=*value; /* only one byte */
- CALL(NewMember(scr, &expr));
- } else if(control&CON_NUM) {
- /* NO strings allowed! */
- CALL(Warn(scr, FPLERR_UNEXPECTED_STRING_STATEMENT));
- /* be able to continue here, we must pass everything that has to
- to with the strings in this expression */
- } else if (*scr->text==CHAR_ASSIGN || (*scr->text==CHAR_PLUS &&
- scr->text[1]==CHAR_ASSIGN)) {
- char array=FALSE;
- char multi=FALSE;
- struct fplStr **string; /* current string */
- char app=(*scr->text==CHAR_PLUS);
-
- if(pident->flags&FPL_READONLY && !(control&CON_DECLARE))
- return FPLERR_READONLY_VIOLATE;
-
- scr->text+=1+app;
- expr->flags|=FPL_ACTION;
- if(pident->data.variable.num) { /* if array member assign */
- Eat(scr);
- if(*scr->text==CHAR_OPEN_BRACE) {
- /* array assign */
- multi=TRUE;
- scr->text++;
- CALL(Eat(scr));
- }
- array=TRUE;
- }
-
- if(!multi) {
- /* single (array) variable assign */
- if(array) {
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0; /* we don't know what was meant! */
- }
- } else
- pos=0;
- string=&pident->data.variable.var.str[pos];
- CALL(Expression(val, scr, CON_STRING, NULL));
- if(!(val->flags&FPL_STRING)) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ASSIGN));
- }
- if(!app && val->flags&FPL_NOFREE) {
- /*
- * Only do this this is not an append action _and_
- * we can't free this string (== someone else is
- * taking care of this string!)
- */
- if(*string) {
- FREE_KIND(*string); /* free old string */
- }
- if(val->val.str) {
- /* duplicate string */
- STRFPLDUP((*string), val->val.str);
- }
- else
- *string=NULL;
- } else {
- CALL(StrAssign(val->val.str, scr, string, app));
- }
- if(*string && MALLOC_STATIC == TypeMem(pident) )
- SwapMem(scr, *string, MALLOC_STATIC);
- if(app && !(val->flags&FPL_NOFREE) && val->val.str)
- /* Only do this if appending! */
- FREE(val->val.str);
- #ifdef STRING_STACK
- if(app && val->val.str)
- /* the string couldn't be freed, but we let them know that
- we don't use it anymore! */
- val->val.str->flags=FPLSTR_UNUSED;
- #endif
- } else {
- /* multi [compound] assign! */
-
- /*
- * Count the preceding open braces to get proper level
- * to assign in.
- */
- while(*scr->text==CHAR_OPEN_BRACE) {
- num++; /* next dimension */
- scr->text++; /* pass it! */
- CALL(Eat(scr));
- }
-
- do {
- while(1) {
- hit=TRUE;
-
- /* parse the controlling braces and commas */
- switch(*scr->text) {
- case CHAR_CLOSE_BRACE:
-
- num--; /* back one dimension */
- if(num>=0 && num<pident->data.variable.num)
- dims[num]=0;
- else {
- CALL(Warn(scr,FPLERR_ILLEGAL_ARRAY));
- num=0; /* force counter to zero! */
- }
- scr->text++;
- break;
- case CHAR_COMMA:
- /*
- * Increase the last dimension member for next loop:
- */
-
- if(num>0 && num<=pident->data.variable.num)
- dims[num-1]++;
- else {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- /* force counter back to top position! */
- num=pident->data.variable.num;
- } scr->text++;
- break;
- case CHAR_OPEN_BRACE:
- num++; /* next dimension */
- scr->text++;
- break;
- default:
- hit=FALSE;
- break;
- }
- if(hit && !ret) {
- CALL(Eat(scr));
- } else
- break;
- }
-
-
- if(!num)
- break;
-
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0; /* force back to sane number */
- }
-
- /* assign! */
-
- string=&pident->data.variable.var.str[pos];
-
- CALL(Expression(val, scr, CON_STRING, NULL));
- if(!(val->flags&FPL_STRING)) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ASSIGN));
- }
-
- if(!app && val->flags&FPL_NOFREE) {
- /*
- * Only do this this is not an append action _and_
- * we can't free this string (== someone else is
- * taking care of this string!)
- */
- if(*string) {
- FREE_KIND(*string); /* free old string */
- }
- if(val->val.str) {
- STRFPLDUP((*string), val->val.str); /* duplicate string */
- }
- else
- *string = NULL;
- } else {
- CALL(StrAssign(val->val.str, scr, string, app));
- }
- if(*string && MALLOC_STATIC == TypeMem(pident))
- SwapMem(scr, *string, MALLOC_STATIC);
-
- if(app && !(val->flags&FPL_NOFREE) && val->val.str) {
- /* only if we're appending! */
- FREE(val->val.str);
- }
-
- #ifdef STRING_STACK
- if(app)
- /* the string couldn't be freed, but we let them know that
- we don't use it anymore! */
- val->val.str->flags=FPLSTR_UNUSED;
- #endif
- /* while */
- } while(1);
- }
- expr->val.str=*string;
- expr->flags|=FPL_STRING|FPL_NOFREE;
- } else {
- if(control&CON_DECLARE)
- expr->val.val=0;
- else if(pident->data.variable.num) {
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0; /* force back to sane number */
- }
- expr->val.str=pident->data.variable.var.str[pos];
- } else
- expr->val.str=pident->data.variable.var.str[0];
- expr->flags|=FPL_STRING|FPL_NOFREE;
- }
- } else {
- /*
- * Integer variable...
- */
- if(control&CON_STRING) {
- /* NO integers allowed! */
- CALL(Warn(scr, FPLERR_UNEXPECTED_INT_STATEMENT));
- }
- #if 0
- if(pident->flags&FPL_READONLY && !(control&CON_DECLARE)) {
- if(!pident->data.variable.num)
- expr->val.val=pident->data.variable.var.val32[0];
- else {
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0; /* force back to sane number */
- }
-
- expr->val.val=pident->data.variable.var.val32[pos];
- }
- } else
- #endif
- if(!expr->operator && !expr->unary &&
- ASSIGN_OPERATOR) {
-
- /* integer assign */
-
- char array=FALSE; /* is it an array variable */
- char multi=FALSE; /* mutiple variable */
- char was=*scr->text;
-
- if(pident->flags&FPL_READONLY && !(control&CON_DECLARE))
- return FPLERR_READONLY_VIOLATE;
-
- expr->flags|=FPL_ACTION;
- if(*scr->text==CHAR_ASSIGN)
- scr->text++;
- else if(scr->text[2]==CHAR_ASSIGN)
- scr->text+=3;
- else
- scr->text+=2;
- if(pident->data.variable.num) { /* if array member assign */
- Eat(scr);
- if(*scr->text==CHAR_OPEN_BRACE) {
-
- /* array assign */
- multi=TRUE;
- scr->text++;
- CALL(Eat(scr));
- }
- array=TRUE;
- }
-
- if(!multi) {
- if(!array)
- pos=0;
- else {
- /* single (array) variable assign */
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0; /* force back to a decent number */
- }
- }
-
- CALL(Expression(val, scr, CON_NORMAL|CON_NUM, NULL));
-
- CALL(CmpAssign(scr, val->val.val,
- &pident->data.variable.var.val32[pos],
- pident->flags, was));
- expr->val.val=pident->data.variable.var.val32[pos];
- } else {
- /* multi [compound] assign */
-
- /*
- * Count the preceding open braces to get proper level
- * to assign in.
- */
- while(*scr->text==CHAR_OPEN_BRACE) {
- num++; /* next dimension */
- scr->text++; /* pass it! */
- CALL(Eat(scr));
- }
-
- do {
- while(1) {
- char hit=TRUE;
-
- /* parse the controlling braces and commas */
- switch(*scr->text) {
- case CHAR_CLOSE_BRACE:
-
- num--; /* back one dimension */
- if(num>=0 && num<pident->data.variable.num)
- dims[num]=0;
- else {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- num=0;
- }
- scr->text++;
- break;
- case CHAR_COMMA:
- /*
- * Increase the last dimension member for next loop:
- */
- if(num>0 && num<=pident->data.variable.num)
- dims[num-1]++;
- else {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- num=pident->data.variable.num;
- }
- scr->text++;
- break;
- case CHAR_OPEN_BRACE:
- num++; /* next dimension */
- scr->text++;
- break;
- default:
- hit=FALSE;
- break;
- }
- if(hit && !ret) {
- CALL(Eat(scr));
- } else
- break;
- }
-
- if(!num)
- break;
-
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0;
- }
-
- /* assign! */
- CALL(Expression(val, scr, CON_NORMAL|CON_NUM, NULL));
- CALL(CmpAssign(scr, val->val.val, &pident->data.variable.var.val32[pos],
- pident->flags, was));
- expr->val.val=pident->data.variable.var.val32[pos];
-
- /* while */
- } while(1);
- }
- expr->flags|=FPL_NOFREE; /* the memory pointed to by the expr->val.val
- is strings of proper variables. Do
- not free them now! */
- } else {
- /*
- * No assignment, primary operator or none at all!
- */
- long *value;
- if(control&CON_DECLARE)
- expr->val.val=0;
- else {
- if(pident->data.variable.num) {
- pos=ArrayNum(num, pident->data.variable.num,
- dims, pident->data.variable.dims);
- if(pos<0) {
- CALL(Warn(scr, FPLERR_ILLEGAL_ARRAY));
- pos=0;
- }
- } else
- pos=0;
- value=&pident->data.variable.var.val32[pos];
-
- if(*point==CHAR_PLUS && point[1]==CHAR_PLUS) {
- /*post increment*/
- if(pident->flags&FPL_READONLY)
- return FPLERR_READONLY_VIOLATE;
- expr->flags|=FPL_ACTION;
- expr->val.val=(*value)++;
- scr->text+=2;
- } else if(*point==CHAR_MINUS && point[1]==CHAR_MINUS) {
- /* post decrement */
- if(pident->flags&FPL_READONLY)
- return FPLERR_READONLY_VIOLATE;
-
- expr->flags|=FPL_ACTION;
- expr->val.val=(*value)--;
- scr->text+=2;
- } else {
- /* plain variable or pre operation */
- if(un=expr->unary) {
- if(un->unary!=OP_PREINC && un->unary!=OP_PREDEC) {
- expr->val.val=*value;
- } else {
- if(pident->flags&FPL_READONLY)
- return FPLERR_READONLY_VIOLATE;
- if(un->unary==OP_PREINC)
- expr->val.val=++(*value);
- else
- expr->val.val=--(*value);
- expr->unary=un->next;
- FREE(un);
- }
- } else
- expr->val.val=*value;
- }
- if(pident->flags&FPL_VARIABLE_LESS32) {
- if(pident->flags&FPL_CHAR_VARIABLE) {
- expr->val.val=(long)((signed char)expr->val.val);
- *value=(long)((signed char)*value);
- } else {
- /* sixteen bits */
- expr->val.val=(long)((signed short)expr->val.val);
- *value=(long)((signed short)*value);
- }
- }
- }
- CALL(NewMember(scr, &expr));
- }
- } /* end of integer handling */
- } else if(ret && (*scr->text!=CHAR_OPEN_PAREN))
- return(ret); /* FPLERR_IDENTIFIER_NOT_FOUND */
- else { /* some sort of function */
- /*
- * FUNCTION HANDLER PART:
- */
-
- struct fplArgument *pass; /* struct pointer to send as argument to
- the function handler */
- long allocspace;
-
- if(ret) {
- if(!(scr->flags&FPLDATA_ALLFUNCTIONS) ||
- *scr->text!=CHAR_OPEN_PAREN)
- /* If the ability to parse all functions isn't turned on, or if
- the following character is not an open parenthesis, fail! */
- return(ret);
- }
-
- num=0; /* number of arguments */
-
- expr->flags|=FPL_OPERAND|FPL_ACTION; /* This sure is action...! */
-
- GETMEM(pass, sizeof(struct fplArgument));
-
- if(!ident) {
- /* The function does not exist as a declared function! */
- STRDUP(pass->name, scr->buf);
- pass->ID=FPL_UNKNOWN_FUNCTION;
- text="o>"; /* optional parameter list as argument! */
- } else {
- pass->name=ident->name;
- pass->ID=ident->data.external.ID;
- text=ident->data.inside.format;
- }
- pass->argc=0;
- pass->key=(void *)scr;
-
- if(!ident || FPL_OPTEXPRARG == ident->data.inside.ret) {
- /*
- * The function we invoked was not found regularly!
- * Set return type!
- */
-
- /*
- * We try to determine whether it should return an int or a string.
- * We interpret the return value as we should do to make it pass
- * as a valid expression. That is, if the flag tells us this
- * should be a string expression to be valid, we take it as a
- * string, but if it tells us its an integer expression, we read
- * it as an integer!!!
- */
-
- if(control&CON_STRING)
- hit = FPL_STRARG;
- else {
- if(control&CON_NUM)
- hit = FPL_INTARG;
- else
- /*
- * We don't know which kind of return code the function
- * should give us!
- */
- hit = FPL_OPTEXPRARG;
- }
-
- } else {
- hit = UPPER(ident->data.inside.ret);
- if(control&CON_STRING && (hit!=FPL_STRARG))
- return FPLERR_UNEXPECTED_INT_STATEMENT;
- if(control&CON_NUM && (hit!=FPL_INTARG))
- return FPLERR_UNEXPECTED_STRING_STATEMENT;
- }
-
- pass->ret = hit;
-
- if(*scr->text!=CHAR_OPEN_PAREN) {
- CALL(Warn(scr, FPLERR_MISSING_PARENTHESES)); /* >warning< */
- } else
- scr->text++;
-
- CALL(Eat(scr));
-
- if(text && *text) {
- unsigned char b='a';
- unsigned char a;
-
- /* if the function takes arguments */
-
- /*
- * Allocate arrays to use for data storage while parsing
- * the arguments. Maximum number of arguments is
- * MAX_ARGUMENTS.
- */
-
- num=strlen(text); /* number of arguments to this function */
-
- if(text[num-1]!=FPL_ARGLIST)
- allocspace=num+1;
- else
- allocspace=MAX_ARGUMENTS;
-
- /*
- * By adjusting the number of allocated bytes to the smallest
- * necessary, my recursive example program used only a fifth
- * as much memory as when always allocating memory for
- * MAX_ARGUMENTS.
- */
-
- /* allocate an array */
- GETMEM(pass->argv, sizeof(char *)*allocspace);
-
- /* allocate new format string */
- GETMEM(pass->format, sizeof(char)*allocspace);
-
- /* allocate allocate-flag string */
- GETMEM(array, sizeof(char)*allocspace);
-
- while(!ret && *scr->text!=CHAR_CLOSE_PAREN && text && *text) {
- b=(*text==FPL_ARGLIST)?b:UPPER(*text);
- if(FPL_OPTARG == b &&
- CHAR_AND == scr->text[0])
- a = FPL_OPTVARARG;
- else
- a = b;
-
- if(pass->argc==allocspace) {
- char *temp;
- GETMEM(temp, sizeof(char *)*(allocspace+MAX_ARGUMENTS));
- memcpy(temp, pass->argv, sizeof(char *)*allocspace);
- FREE(pass->argv);
- pass->argv=(void **)temp;
-
- GETMEM(temp, sizeof(char)*(allocspace+MAX_ARGUMENTS));
- memcpy(temp, pass->format, sizeof(char)*allocspace);
- FREE(pass->format);
- pass->format=temp;
-
- GETMEM(temp, sizeof(char)*(allocspace+MAX_ARGUMENTS));
- memcpy(temp, array, sizeof(char)*allocspace);
- FREE(array);
- array=temp;
-
- allocspace += MAX_ARGUMENTS;
- }
-
- switch(a) {
- case FPL_OPTEXPRARG:
- case FPL_OPTARG:
- case FPL_STRARG:
- CALL(Expression(val, scr, (a==FPL_STRARG?CON_STRING:0), NULL));
- if(a==FPL_STRARG && !(val->flags&FPL_STRING)) {
- CALL(Warn(scr, FPLERR_ILLEGAL_PARAMETER));
- }
-
- if(a==FPL_STRARG || val->flags&FPL_STRING) {
-
- /* Enter string symbol in the created format string! */
- pass->format[pass->argc]=FPL_STRARG;
-
- if(val->val.str) {
- /* Set this to TRUE if deallocation is wanted on this
- string after the function call! */
- array[pass->argc]=!(val->flags&FPL_NOFREE);
- /*
- * Point to the string (that is zero terminated)!
- */
- pass->argv[pass->argc]=val->val.str->string;
- } else {
- GETMEM(string, sizeof(struct fplStr));
- memset(string, 0, sizeof(struct fplStr));
- pass->argv[pass->argc]=string->string;
- array[pass->argc]=1; /* allocation has been done! */
- }
- } else {
- pass->format[pass->argc]=FPL_INTARG;
- pass->argv[pass->argc]=(void *)val->val.val;
- }
- pass->argc++;
- break;
- case FPL_INTARG:
- CALL(Expression(val, scr, CON_NUM, NULL));
- pass->format[pass->argc]=FPL_INTARG;
- pass->argv[pass->argc++]=(void *)val->val.val;
- break;
- case FPL_OPTVARARG:
- case FPL_STRVARARG:
- case FPL_INTVARARG:
- case FPL_INTARRAYVARARG:
- case FPL_STRARRAYVARARG:
- if(*scr->text != CHAR_AND) {
- hit = FPLERR_ILLEGAL_REFERENCE;
- }
- else {
- scr->text++;
- hit = FPL_OK;
- }
- CALL(Getword(scr));
- /* Use the `pident' pointer here, cause the `ident' pointer
- is already being used by the function we're about to
- invoke! */
- CALL(GetIdentifier(scr, scr->buf, &pident));
-
- if(hit) {
- /* missing &-character! */
- if(pident->flags&FPL_REFERENCE)
- /* get the referenced variable instead! */
- pident = pident->data.variable.ref;
- else
- return FPLERR_ILLEGAL_REFERENCE; /* no reference! */
- }
-
- if(FPL_INTARRAYVARARG == a || FPL_STRARRAYVARARG == a) {
- if(!pident->data.variable.num)
- return FPLERR_ILLEGAL_REFERENCE;
- }
- else if(FPL_OPTVARARG != a && pident->data.variable.num)
- /* only straight variables! */
- return FPLERR_ILLEGAL_PARAMETER;
-
- if( (pident->flags&FPL_INT_VARIABLE &&
- (a==FPL_STRVARARG || a == FPL_STRARRAYVARARG)) ||
- (pident->flags&FPL_STRING_VARIABLE &&
- (a==FPL_INTVARARG || a == FPL_INTARRAYVARARG))) {
- CALL(Warn(scr, FPLERR_ILLEGAL_VARIABLE));
- /* can't copy wrong variable! */
- pass->argv[pass->argc]=NULL;
- } else
- pass->argv[pass->argc]=(void *)pident;
-
- pass->format[pass->argc++]=
- (pident->flags&FPL_STRING?
- (pident->data.variable.num?FPL_STRARRAYVARARG:FPL_STRVARARG):
- (pident->data.variable.num?FPL_INTARRAYVARARG:
- FPL_INTVARARG));
- Eat(scr);
- break;
- default:
- CALL(Warn(scr, FPLERR_ILLEGAL_PARAMETER));
- break; /* just ignore it and be happy! */
- }
- if(*text!=FPL_ARGLIST)
- text++;
- if(*scr->text==CHAR_COMMA) {
- scr->text++;
- CALL(Eat(scr)); /* eat white space! */
-
- }
- }
- pass->format[pass->argc]=CHAR_ASCII_ZERO;
- if(text && *text && !(*text&CASE_BIT)) {
- return FPLERR_MISSING_ARGUMENT;
- /*
- * This is a serious mis-use. The function is called with to few
- * parameters. At least one parameter missing is a required one.
- * I really can't figure out a way to survive such a shock!
- */
- }
- } else
- pass->format=NULL;
- if(*scr->text!=CHAR_CLOSE_PAREN) {
- CALL(Warn(scr, FPLERR_TOO_MANY_PARAMETERS)); /* too many parameters! */
- /* It's ok to continue without the parenthesis! */
- } else
- scr->text++;
-
- /*
- * Call the function!
- */
-
- CALL(CallFunction(scr, pass, ident));
-
- if(!ident) {
- /*
- * The function we invoked was not found regularly!
- * Free the name we allocated temporarily and set
- * return type to optional!
- */
- FREE(pass->name); /* the name was strdup()'ed! */
- }
-
- if(FPL_OPTEXPRARG == hit) {
-
- CALL(GetMessage(scr, FPLMSG_RETURN_INT, &msg));
- if(!msg) {
- /* There is no 'int' return. Check if there is any 'string'
- return, otherwise say it is an 'int' anyway! */
- CALL(GetMessage(scr, FPLMSG_RETURN_STRING, &msg));
- if(!msg)
- /* no string either, default to int! */
- hit = FPL_INTARG;
- else
- /* found string, it returned a 'string' !!! */
- hit = FPL_STRARG;
- } else {
- /* There is a return 'int' message! This may well be a
- function returning int! */
- hit = FPL_INTARG;
- }
-
- }
-
- if(hit==FPL_STRARG)
- /* if the return value should be a string: */
- HandleString(scr, expr);
- else {
- /* only if integer! or the function is non-existent */
- CALL(GetMessage(scr, FPLMSG_RETURN_INT, &msg));
- expr->val.val=(msg?(long)msg->message[0]:0);
- CALL(NewMember(scr, &expr));
- if(msg)
- CALL(DeleteMessage(scr, msg));
- }
- while(pass->argc--) {
- if(pass->format[pass->argc]==FPL_STRARG && array[pass->argc]) {
- /* free the string if it's been marked to be freed!! */
- FREE((char *)pass->argv[pass->argc]-
- offsetof(struct fplStr, string));
- }
- }
- if(pass->format) {
- FREE(pass->argv);
- FREE(pass->format);
- FREE(array);
- }
- FREE(pass);
- }
- } else {
-
- pos=0;
- switch(*scr->text) {
- case CHAR_MULTIPLY:
- /*
- * This is the 'contents of' operator!
- * The contents of the variable that follows this sign should
- * get the following rvalue.
- * Of course, we must first check that this really is a
- * 'pointer' to a variable.
- * If we declare this, make sure that it doesn't point to
- * anything at all!
- */
-
- while(*++scr->text==CHAR_MULTIPLY); /* just in case! */
-
- CALL(Getword(scr));
- if(control&CON_DECLARE) {
- return FPLERR_SYNTAX_ERROR; /* not yet supported */
- }
- else {
- CALL(GetIdentifier(scr, scr->buf, &ident));
- if(!(ident->flags&FPL_REFERENCE))
- return FPLERR_ILLEGAL_REFERENCE; /* referenced a non-reference! */
- if(!ident->data.variable.ref)
- return FPLERR_ILLEGAL_REFERENCE; /* illegal reference! */
-
- ident = ident->data.variable.ref; /* use the "actual" variable! */
-
- /* we have an identifier and the level is OK! */
- control |= CON_IDENT|CON_LEVELOK;
- continue; /* now we have the pointer for the *real* variable! */
- }
- break;
- case CHAR_ZERO:
- /*
- * Numbers starting with a '0' can be hex/oct/bin.
- */
- if(control&CON_STRING) {
- /* NO integers allowed! */
- return FPLERR_UNEXPECTED_INT_STATEMENT;
- }
- switch(scr->text[1]) {
- case CHAR_X:
- case CHAR_UPPER_X:
- /* hexadecimal number parser */
- for(scr->text+=2; isxdigit(*scr->text); scr->text++)
- expr->val.val=expr->val.val*16+ (isdigit(*scr->text)?
- *scr->text-CHAR_ZERO:
- UPPER(*scr->text)-CHAR_UPPER_A+10);
- break;
- case CHAR_B:
- case CHAR_UPPER_B:
- /* binary number parser */
- for(scr->text+=2;*scr->text==CHAR_ZERO || *scr->text==CHAR_ONE;)
- expr->val.val=expr->val.val*2+ *scr->text++ - CHAR_ZERO;
- break;
- case CHAR_ZERO:
- case CHAR_ONE:
- case CHAR_TWO:
- case CHAR_THREE:
- case CHAR_FOUR:
- case CHAR_FIVE:
- case CHAR_SIX:
- case CHAR_SEVEN:
- /* octal number parser */
- for(scr->text++; isodigit(*scr->text);)
- expr->val.val=expr->val.val*8+ *scr->text++ - CHAR_ZERO;
- break;
- default:
- /* a single zero is simply 0 */
- scr->text++;
- expr->val.val=0;
- break;
- }
- CALL(NewMember(scr, &expr));
- break;
- /* end of case CHAR_ZERO: */
-
- case CHAR_ONE:
- case CHAR_TWO:
- case CHAR_THREE:
- case CHAR_FOUR:
- case CHAR_FIVE:
- case CHAR_SIX:
- case CHAR_SEVEN:
- case CHAR_EIGHT:
- case CHAR_NINE:
- /*
- * We hit a number between 1 and 9.
- */
- if(control&CON_STRING) {
- /* NO integers allowed! */
- CALL(Warn(scr, FPLERR_UNEXPECTED_INT_STATEMENT));
- }
- do
- expr->val.val= expr->val.val*10 + *scr->text++ - CHAR_ZERO;
- while(isdigit(*scr->text));
- CALL(NewMember(scr, &expr));
- break;
-
- case CHAR_QUOTATION_MARK:
- if(control&CON_NUM) {
- /* NO integers allowed! */
- CALL(Warn(scr, FPLERR_UNEXPECTED_STRING_STATEMENT));
- }
- CALL(Convert(val, scr));
- /* This returned a string! */
- expr->val.str=val->val.str;
- expr->flags=FPL_STRING;
- break;
-
- case CHAR_APOSTROPHE:
- /*
- * Apostrophes surround character. Returns ASCII code.
- */
- if(control&CON_STRING) {
- /* NO integers allowed! */
- CALL(Warn(scr, FPLERR_UNEXPECTED_INT_STATEMENT));
- }
- CALL(ReturnChar((scr->text++, scr), &expr->val.val, FALSE));
- if(*scr->text!=CHAR_APOSTROPHE) {
- CALL(Warn(scr, FPLERR_MISSING_APOSTROPHE)); /* >warning< */
- /* just continue as nothing has ever happened! */
- } else
- scr->text++;
- CALL(NewMember(scr, &expr));
- break;
-
- case CHAR_OPEN_PAREN:
- CALL(Expression(val, (++scr->text, scr), CON_GROUNDLVL|CON_NUM, NULL));
- if(*scr->text!=CHAR_CLOSE_PAREN) {
- CALL(Warn(scr, FPLERR_MISSING_PARENTHESES)); /* >warning< */
- /* Go on anyway! */
- } else
- scr->text++;
- expr->val.val=val->val.val;
- CALL(NewMember(scr, &expr));
- break;
-
- case CHAR_NOT_OPERATOR:
- CALL(AddUnary(scr, expr, OP_NOT));
- ++scr->text;
- break;
-
- case CHAR_ONCE_COMPLEMENT:
- CALL(AddUnary(scr, expr, OP_COMPL));
- ++scr->text;
- break;
-
- case CHAR_PLUS:
- if(scr->text[1]==CHAR_PLUS) {
- expr->flags|=FPL_ACTION;
- scr->text+=2;
- CALL(AddUnary(scr, expr, OP_PREINC));
- } else {
- CALL(AddUnary(scr, expr, OP_PLUS));
- scr->text++;
- }
- break;
-
- case CHAR_MINUS:
- if(scr->text[1]==CHAR_MINUS) {
- expr->flags|=FPL_ACTION;
- scr->text+=2;
- CALL(AddUnary(scr, expr, OP_PREDEC));
- } else {
- CALL(AddUnary(scr, expr, OP_MINUS));
- scr->text++;
- }
- break;
-
- default:
-
- if((*scr->text==CHAR_SEMICOLON && control&CON_SEMICOLON) ||
- (*scr->text==CHAR_CLOSE_PAREN && control&CON_PAREN)
- && basexpr==expr && expr->operator==OP_NOTHING) {
- /* for(;;) support.
- There must not have been a previous operand or operator */
- pos=expr->val.val=TRUE;
- } else { /* no operand results in error! */
- CALL(Warn(scr, FPLERR_MISSING_OPERAND)); /* WARNING! */
- expr->operator=OP_NOTHING; /* reset */
- }
- break;
- }
- if(pos)
- break;
- }
-
- } else { /* waiting for operator */
- char *point=scr->text;
-
- switch(*scr->text) {
- case CHAR_ASSIGN:
- if(scr->text[1]==CHAR_ASSIGN) {
- expr->operator=OP_EQUAL;
- scr->text+=2;
- }
- break;
- case CHAR_AND:
- if(scr->text[1]==CHAR_AND) {
- /*
- * This is a logical AND (&&)
- */
- scr->text+=2;
-
- /*
- * Get result from everything to the left of this!
- */
- CALL(Calc(scr, val, basexpr));
-
- /*
- * Clean the expression so far.
- */
- Clean(scr, basexpr); /* erase the list */
-
- /*
- * Start a new list with this result
- */
- GETMEM(expr, sizeof(struct Expr));
- memset(expr, 0, sizeof(struct Expr));
- basexpr=expr;
- expr->val.val = val->val.val;
-
- if(!expr->val.val) {
- /*
- * In this case, its like in the 'a && b' expression and 'a'
- * equals 0. Then we should skip the 'b' expression.
- */
- CALL(ScanForNext(scr, OP_LOGAND));
- expr->flags = FPL_OPERAND;
- }
- continue;
-
- } else {
- expr->operator=OP_BINAND;
- scr->text++;
- }
- break;
- case CHAR_OR:
- if(scr->text[1]==CHAR_OR) {
- /*
- * This is a logical OR operator (||)
- */
- scr->text+=2;
-
- /*
- * Get result from everything to the left of this!
- */
- CALL(Calc(scr, val, basexpr));
-
- /*
- * Clean the expression so far.
- */
- Clean(scr, basexpr); /* erase the list */
-
- /*
- * Start a new list with this result
- */
- GETMEM(expr, sizeof(struct Expr));
- memset(expr, 0, sizeof(struct Expr));
- basexpr=expr;
- expr->val.val = val->val.val;
-
- if(expr->val.val) {
- /*
- * In this case, its like in the 'a || b' expression and 'a'
- * equals 1. Then we should skip the 'b' expression.
- */
- CALL(ScanForNext(scr, OP_LOGOR));
- expr->flags = FPL_OPERAND;
- }
- continue;
-
- } else {
- expr->operator=OP_BINOR;
- scr->text++;
- }
- break;
- case CHAR_PLUS:
- expr->operator=OP_PLUS;
- ++scr->text;
- break;
- case CHAR_MINUS:
- expr->operator=OP_MINUS;
- ++scr->text;
- break;
- case CHAR_QUESTION:
- ++scr->text;
- /*
- * This is the first operator in a conditional operator sequence (?)
- */
-
- /*
- * Get result from everything to the left of this!
- */
- CALL(Calc(scr, val, basexpr));
-
- /*
- * Clean the expression so far.
- */
- Clean(scr, basexpr); /* erase the list */
-
- /*
- * Start a new list with this result
- */
- GETMEM(expr, sizeof(struct Expr));
- memset(expr, 0, sizeof(struct Expr));
- expr->flags = FPL_OPERAND;
- basexpr=expr;
-
- if(val->val.val) {
- /*
- * In this case, its like in the 'a ? b : c' expression and 'a'
- * equals 1. Then we should skip the 'c' expression.
- */
- CALL(Expression(val, scr, CON_NORMAL, NULL));
- if(*scr->text++!=CHAR_COLON)
- return FPLERR_ILLEGAL_CONDOP;
- CALL(ScanForNext(scr, OP_COND2));
- }
- else {
- /*
- * In this case, its like in the 'a ? b : c' expression and 'a'
- * equals 0. Then we should skip the 'b' expression.
- */
- CALL(ScanForNext(scr, OP_COND1));
- if(*scr->text++!=CHAR_COLON)
- return FPLERR_ILLEGAL_CONDOP;
- CALL(Expression(val, scr, CON_NORMAL, NULL));
- }
- expr->val.val = val->val.val;
- continue; /* check for next operator */
-
- break;
- #if 0
- case CHAR_COLON:
- if(conditional) {
- /* only if preceeded with the regular '?' operator! */
- conditional--;
- expr->operator=OP_COND2;
- ++scr->text;
- }
- break;
- #endif
- case CHAR_MULTIPLY:
- expr->operator=OP_MULTIPLY;
- ++scr->text;
- break;
- case CHAR_DIVIDE:
- expr->operator=OP_DIVISION;
- ++scr->text;
- break;
- case CHAR_REMAIN:
- expr->operator=OP_REMAIN;
- ++scr->text;
- break;
- case CHAR_XOR:
- expr->operator=OP_BINXOR;
- ++scr->text;
- break;
- case CHAR_LESS_THAN:
- if(scr->text[1]==CHAR_ASSIGN) {
- scr->text+=2;
- expr->operator=OP_LESSEQ;
- } else if(scr->text[1]==CHAR_LESS_THAN) {
- scr->text+=2;
- expr->operator=OP_SHIFTL;
- } else {
- scr->text++;
- expr->operator=OP_LESS;
- }
- break;
- case CHAR_GREATER_THAN:
- if(scr->text[1]==CHAR_ASSIGN) {
- expr->operator= OP_GRETEQ;
- scr->text+=2;
- } else if(scr->text[1]==CHAR_GREATER_THAN) {
- scr->text+=2;
- expr->operator=OP_SHIFTR;
- } else {
- scr->text++;
- expr->operator=OP_GRET;
- }
- break;
- case CHAR_NOT_OPERATOR:
- if(scr->text[1]==CHAR_ASSIGN) {
- expr->operator=OP_NOTEQ;
- scr->text+=2;
- }
- break;
- case CHAR_COMMA:
- if(control&CON_GROUNDLVL) {
- Clean(scr, basexpr);
- GETMEM(basexpr, sizeof(struct Expr));
- expr=basexpr;
- expr->val.val=0;
- expr->unary=NULL;
- expr->operator=expr->flags=OP_NOTHING;
- expr->next=NULL;
- scr->text++;
- }
- break;
- }
- if(point==scr->text)
- break;
- expr->flags&=~FPL_OPERAND; /* clear the operand bit */
- }
- }
-
- if(!(control&(CON_DECLARE /* |CON_ACTION */ ))) {
- /*
- * Get result of the current expression only if this isn't called
- * as a declaring (no one wants the return code from 'int a'!)
- * or a stand-alone (they have no receiver anyway) statement.
- */
- CALL(Calc(scr, val, basexpr));
-
- /*
- * If this was a stand alone statement, including no action returns an
- * error!
- */
- if(control&CON_ACTION && !(val->flags&FPL_ACTION)) {
- CALL(Warn(scr, FPLERR_NO_ACTION));
- /* but we can just as good keep on anyway! */
- }
- }
-
- Clean(scr, basexpr); /* erase the rest of the list */
- if(dims)
- FREE(dims);
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * ReturnCode Calc();
- *
- * Returns the result in the first Expr struct of the expression that
- * the second parameter holds. This function does not free the expression
- * list.
- *
- *******/
-
- static ReturnCode
- Calc(struct Data *scr,
- struct Expr *val,
- struct Expr *basexpr)
- {
- /* lower value=higher priority. Order as the operator list in script.h:
- *| + - / * << >> % & | ^ && || ~ ? : == <= >= < > != ! */
- const static unsigned char priority[]={
- 255, 1, 1, 0, 0, 2, 2, 0, 5, 7, 6, 8, 9, 255, 10, 10, 4, 3, 3, 3, 3, 4, 255
- };
-
- ReturnCode ret;
- unsigned char pri, minpri=255, maxpri=0;
- struct Expr *expr=basexpr, *last;
- struct Unary *un, *next;
-
- /* first all Unary expressions */
- if(!(expr->flags&FPL_STRING)) {
- while(expr) {
- if(priority[expr->operator]<minpri)
- minpri=priority[expr->operator]; /* get the lowest priority */
- if(priority[expr->operator]>maxpri && expr->operator!=OP_NOTHING)
- maxpri=priority[expr->operator]; /* get the highest priority */
- if(expr->flags&FPL_STRING) {
- CALL(Warn(scr, FPLERR_ILLEGAL_VARIABLE));
- /*
- * A string among the integers!
- * We remove this and try next!
- */
-
- last=expr->next;
- FREE(expr); /* delete this bastard from the expression!!! */
- expr=last;
- } else {
- un=expr->unary;
- while(un) {
- switch(un->unary) {
- case OP_NOT:
- expr->val.val=!expr->val.val;
- break;
- case OP_COMPL:
- expr->val.val=~expr->val.val;
- break;
- case OP_MINUS:
- expr->val.val=-expr->val.val;
- break;
- /*simply ignored!
- case OP_PLUS:
- break;
- */
- case OP_PREDEC:
- case OP_PREINC:
- CALL(Warn(scr, FPLERR_ILLEGAL_PREOPERATION));
- /* just ignore it! */
- }
- next=un->next;
- FREE(un);
- un=next;
- }
- }
- expr=expr->next;
- }
- }
- /*
- * Calculate all members of the linked list in the proper way and put
- * the result in "val->val.val" before returning "ret". Check for operators
- * with priority within `minpri' and `maxpri' which we got in the loop
- * above.
- *
- * Check priority level by priority level and perform the right actions.
- * When reaching the maxpri, there is only one number left: the result!
- */
-
- for(pri=minpri; pri<=maxpri; pri++) {
- last=expr=basexpr;
- while(expr=expr->next) {
- if(priority[expr->operator]==pri) {
- last->flags|=expr->flags;
- switch(expr->operator) {
- case OP_MULTIPLY:
- last->val.val*=expr->val.val;
- break;
- case OP_DIVISION:
- if(!expr->val.val) {
- CALL(Warn(scr, FPLERR_DIVISION_BY_ZERO));
- /* we give a zero as result! */
- last->val.val=0;
- } else
- last->val.val/=expr->val.val;
- break;
- case OP_REMAIN:
- if(!expr->val.val) {
- CALL(Warn(scr, FPLERR_DIVISION_BY_ZERO));
- last->val.val=0;
- } else
- last->val.val%=expr->val.val;
- break;
- case OP_SHIFTL:
- last->val.val<<=expr->val.val;
- break;
- case OP_SHIFTR:
- last->val.val>>=expr->val.val;
- break;
- case OP_BINAND:
- last->val.val&=expr->val.val;
- break;
- case OP_BINOR:
- last->val.val|=expr->val.val;
- break;
- case OP_BINXOR:
- last->val.val^=expr->val.val;
- break;
- case OP_PLUS:
- last->val.val+=expr->val.val;
- break;
- case OP_MINUS:
- last->val.val-=expr->val.val;
- break;
- case OP_EQUAL:
- last->val.val=last->val.val==expr->val.val;
- break;
- case OP_NOTEQ:
- last->val.val=last->val.val!=expr->val.val;
- break;
- case OP_LESSEQ:
- last->val.val=last->val.val<=expr->val.val;
- break;
- case OP_LESS:
- last->val.val=last->val.val<expr->val.val;
- break;
- case OP_GRETEQ:
- last->val.val=last->val.val>=expr->val.val;
- break;
- case OP_GRET:
- last->val.val=last->val.val>expr->val.val;
- break;
- case OP_LOGOR:
- last->val.val=last->val.val||expr->val.val;
- break;
- case OP_LOGAND:
- last->val.val=last->val.val&&expr->val.val;
- break;
- case OP_COND1:
- if(expr->next && expr->next->operator==OP_COND2) {
- last->val.val=last->val.val?expr->val.val:expr->next->val.val;
- } else {
- CALL(Warn(scr, FPLERR_ILLEGAL_CONDOP)); /* WARNING! */
- last->val.val=expr->val.val; /* get the number we have! */
- }
- break;
- }
- last->next=expr->next;
- FREE(expr);
- expr=last;
- } else
- last=expr;
- }
- }
- val->val.val=basexpr->val.val; /* get the final value */
- val->flags=basexpr->flags; /* copy the flags */
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * AddUnary();
- *
- * Build a linked list on the unary member of the Expr struct!
- *
- ******/
-
- static ReturnCode
- AddUnary(struct Data *scr,
- struct Expr *expr,
- Operator unary)
- {
- struct Unary *next=expr->unary;
-
- GETMEM(expr->unary, sizeof(struct Unary));
- expr->unary->unary=unary;
- expr->unary->next=next;
-
- return(FPL_OK);
- }
-
-
- /**********************************************************************
- *
- * Clean()
- *
- * Erases every track of the linked TalStruct list...
- *
- ******/
-
- static void Clean(struct Data *scr, struct Expr *basexpr)
- {
- struct Expr *last;
- while(basexpr) {
- last=basexpr->next;
- FREE(basexpr);
- basexpr=last;
- }
- }
-
- /**********************************************************************
- *
- * HandleString();
- *
- * Assigns the proper members in the Expr struct after a respons from
- * a user specified function.
- *
- *****/
-
- static void INLINE HandleString(struct Data *scr,
- struct Expr *expr)
- {
- struct fplMsg *msg;
- GetMessage(scr, FPLMSG_RETURN_STRING, &msg);
- if(!msg || !msg->message[0])
- /* We got a zero length string or no string at all! */
- expr->val.str=NULL; /* no string! */
- else
- expr->val.str=(struct fplStr *)msg->message[0]; /* the copied string! */
-
- expr->flags=FPL_STRING|FPL_ACTION;
- if(msg)
- DeleteMessage(scr, msg);
- }
-
- /**********************************************************************
- *
- * Convert()
- *
- * Converts the following "string" in the line to a string which it returns.
- *
- *********/
-
- static ReturnCode INLINE Convert(struct Expr *expr, struct Data *scr)
- {
- ReturnCode ret=FPL_OK;
- long a;
- unsigned long pos=0; /* start position */
-
- struct fplStr *pointer, *pek;
-
- expr->flags|=FPL_STRING;
-
- #ifdef STRING_STACK
- /*
- First, check with the static string stack to see if this string
- has already been parsed and is ready to simply restore.
- Put this string as most recently restored.
- */
-
- /*
- StringFromStack() uses the scr->text pointer to determine which string
- we want to have. It also moves our program pointer to the end of the
- string if it is there.
- */
- if(scr->strings_in_stack_max>0) {
- CALL(StringFromStack(scr, &pointer));
- if(pointer) {
- expr->val.str=pointer;
- expr->flags|=FPL_NOFREE|FPL_STACKED;
- return FPL_OK;
- }
- }
- #endif
-
- GETMEM(pointer, sizeof(struct fplStr) + ADDSTRING_DEFAULT);
- /* create default string space */
-
- pointer->alloc=ADDSTRING_DEFAULT;
- pointer->len=0;
-
- expr->val.str=pointer;
-
- #ifdef DEBUG
- CheckMem(scr, pointer);
- #endif
- do {
- scr->text++;
- while(*scr->text!=CHAR_QUOTATION_MARK) {
- CALL(ReturnChar(scr, &a, TRUE));
- if(a<256) {
- pointer->string[pos]=a;
- if(++pos>=pointer->alloc) {
- GETMEM(pek, (pointer->alloc+=ADDSTRING_INC)+sizeof(struct fplStr));
- memcpy(pek, pointer, pos+sizeof(struct fplStr));
- FREE(pointer);
- pointer=pek;
- expr->val.str=pointer;
- }
- }
- }
- scr->text++;
- CALL(Eat(scr));
- } while(*scr->text==CHAR_QUOTATION_MARK);
- pointer->string[pos]=0; /* zero terminate */
- pointer->len=pos; /* length of string */
- expr->val.str=pointer;
- #ifdef STRING_STACK
- /*
- We push our newly scanned string on the string stack. Very useful if
- this string is reffered in i.e a loop.
- */
- if(scr->strings_in_stack_max>0) {
- CALL(StringToStack(scr, &pointer));
- if(pointer)
- /* no one may free a string in the stack! */
- expr->flags|=FPL_NOFREE|FPL_STACKED;
- }
- #endif
-
- return(ret);
- }
-
- #ifdef STRING_STACK
- static ReturnCode INLINE StringToStack(struct Data *scr,
- struct fplStr **string)
- {
- if(scr->stringstackptr >= scr->strings_in_stack_max) {
- FREE(scr->stringkeeper[ 0 ]); /* free the previous holder of that position! */
- scr->stringstackptr = 0;
- } else
- scr->strings_in_stack_now++;
-
- scr->stringstack[ current_entry ].string = *string;
- scr->stringstack[ current_entry ].text = scr->text;
- scr->stringstack[ current_entry ].prg = scr->prg;
- scr->stringstack[ current_entry ].virprg = scr->virprg;
- scr->stringstackptr++;
- }
-
- static ReturnCode INLINE StringFromStack(struct Data *scr,
- struct fplStr **string)
- {
- const long num = scr->stringstackptr;
- const long max = scr->strings_in_stack_max;
- long count;
- for(count=0; count<scr->strings_in_stack_now; count++) {
- if(scr->stringprogram[ (num-count) >= 0 ?
- num-count :
- max-count] == scr->text) {
- *string = scr->stringstack[ count ].string;
- scr->text = scr->stringstack[ count ].text;
- scr->prg = scr->stringstack[ count ].prg;
- scr->virprg = scr->stringstack[ count ].virprg;
- return FPL_OK;
- }
- }
- *string=NULL;
- return FPL_OK;
- }
-
- #endif
-
- /**********************************************************************
- *
- * GetArrayInfo()
- *
- * Read the []'s and store the information. Make sure you're standing on
- * the open bracket!
- *
- * Set the int num points to, to any number if you want to limit the number
- * of dimension reads.
- */
-
- static ReturnCode INLINE GetArrayInfo(struct Data *scr,
- long *dims, /* long array */
- long *num, /* number of dims */
- long control,
- char *name) /* variable name */
- {
- struct Expr *val;
- ReturnCode ret=FPL_OK;
- long maxnum=*num;
- GETMEM(val, sizeof(struct Expr));
- *num=0;
- if(*scr->text==CHAR_OPEN_BRACKET) {
- do {
- scr->text++; /* pass the open bracket */
- /* eval the expression: */
- CALL(Expression(val, scr, CON_GROUNDLVL|CON_NUM, NULL));
-
- if(*scr->text!=CHAR_CLOSE_BRACKET) {
- /* no close bracket means error */
- CALL(Warn(scr, FPLERR_MISSING_BRACKET)); /* >warning< */
- /* go on anyway! */
- } else
- scr->text++;
-
- if(val->val.val<(control&CON_DECLARE?1:0)) {
- /* illegal result of the expression */
- /*
- * Write back the original variable name to the buffer!
- */
- strcpy(scr->buf, name);
- ret = FPLERR_ILLEGAL_ARRAY;
- break;
- }
-
- dims[(*num)++]=val->val.val; /* Add another dimension */
- if(*num==maxnum) {
- /* we've hit the roof! */
- break;
- } else if(*num==MAX_DIMS) {
- /* if we try to use too many dimensions... */
- ret=FPLERR_ILLEGAL_ARRAY;
- /*
- * Write back the original variable name to the buffer!
- */
- strcpy(scr->buf, name);
- break;
- }
- /*
- * Go on as long there are braces and we are declaring OR
- * as long the `num' variable tells us (you, know: when
- * you want to read character five in a member of a
- * three dimensional string array, it could look like
- * "int a=string[2][3][4][5];" ... :-)
- */
- } while(*scr->text==CHAR_OPEN_BRACKET);
- }
- FREE(val);
- return(ret);
- }
-
- /**********************************************************************
- *
- * ArrayNum()
- *
- * Return which array position we should look in when the user wants the
- * array member presented as a number of dimensions and an array with the
- * dimension sizes.
- *
- ******/
-
- long REGARGS
- ArrayNum(long num, /* number of dimensions specified */
- long dnum, /* number of dimensions declared */
- long *dims, /* dimensions specified */
- long *decl) /* declared dimension information */
- {
- long i;
- long pos=0;
- long base=1;
- if(num!=dnum)
- /*
- * Then we can't get proper information!!!
- */
- return(-1);
- for(i=0; i<num; i++) {
- if(dims[i]>=decl[i])
- return(-1);
-
- pos+=dims[i]*base;
- base*=decl[i];
- }
- return(pos);
- }
-
-
- /**********************************************************
- *
- * CallFunction()
- *
- * Calls a function. Internal, external or inside!!
- *
- *******/
-
- static ReturnCode INLINE CallFunction(struct Data *scr,
- struct fplArgument *pass,
- struct Identifier *ident)
- {
- ReturnCode ret;
- if(ident && ident->flags&FPL_INSIDE_FUNCTION) {
- CALL(inside(scr, pass, ident));
- } else if(ident && ident->flags&FPL_INTERNAL_FUNCTION) {
- CALL(functions(pass));
- } else { /* if (EXTERNAL_FUNCTION) */
- pass->funcdata=ident?ident->data.external.data:(void *)NULL;
-
- #if defined(AMIGA) && defined(SHARED)
- if(ret=CheckStack(scr, scr->stack_limit, scr->stack_margin)) {
- if(ret==1)
- return(FPLERR_OUT_OF_MEMORY);
- else
- return(FPLERR_OUT_OF_STACK);
- }
- #endif
-
- if(ident && ident->data.external.func) {
- /*
- * If this is non-zero, a function specific function pointer
- * has been assigned to it! In that case we should call that
- * function instead of the traditional, global one!
- */
- CALL(InterfaceCall(scr, pass, ident->data.external.func));
- } else {
- CALL(InterfaceCall(scr, pass, scr->function));
- }
-
- }
- return(FPL_OK);
- }
-
- /**********************************************************************
- *
- * inside();
- *
- * This function takes care of the inside function callings within a
- * FPL program (or in a FPL program where the function was declared using
- * `export').
- *
- ******/
-
- static ReturnCode INLINE inside(struct Data *scr,
- struct fplArgument *arg,
- struct Identifier *func)
- {
- /*
- * The function has been declared as an `inside' one.
- */
-
- ReturnCode ret=FPL_OK;
- struct Identifier *pident; /* pointer to identifier */
- struct Identifier *ident;
- char *t=scr->text;
- struct Local *locals=NULL;
- long p=scr->prg;
- char *file=scr->prog->name;
- long vp=scr->virprg;
- char *vf=scr->virfile;
- char count; /* parameter counter */
- char *text;
- struct Condition con;
- struct Expr *val;
- struct fplStr *string;
- char oldret;
- static unsigned long inttags[]={FPLSEND_INT, 0, FPLSEND_DONE};
- static unsigned long strtags[]={FPLSEND_STRING, 0, FPLSEND_STRLEN, 0,
- FPLSEND_DONE};
- char cont;
- long search;
- struct Program *prog=scr->prog;
- struct fplVariable *tempvar;
- char reference;
-
- GETMEM(val, sizeof(struct Expr));
- if(file!=func->data.inside.file) {
- struct Program *prog=scr->programs;
- while(prog) {
- if(prog->name && !strcmp(prog->name, func->data.inside.file))
- break;
- prog=prog->next;
- }
- if(prog) {
- CALL(LeaveProgram(scr, scr->prog));
- CALL(GetProgram(scr, prog));
- scr->prog=prog;
- } else
- return(FPLERR_INTERNAL_ERROR); /* This is a dead-end error! */
- }
-
- if(func->flags&FPL_INSIDE_NOTFOUND) {
- /*
- * We have no current information about where this function
- * is to be found. Search for it and store the location in
- * ->text and ->prg.
- */
-
- cont=TRUE;
- search=(func->data.inside.ret==FPL_STRARG)?CMD_STRING:
- (func->data.inside.ret==FPL_INTARG)?CMD_INT:CMD_VOID;
-
- /*
- * Start searching from the declaration position to enable local functions!
- */
-
- scr->text=(&scr->prog->program)[scr->prog->startprg-1]+
- func->data.inside.col;
- scr->prg=func->data.inside.prg;
- scr->virprg=func->data.inside.virprg;
- scr->virfile=func->data.inside.virfile;
- while(cont && !ret) {
- switch(*scr->text) {
- case CHAR_OPEN_BRACE:
- /* ...go to the corresponding brace */
- ret=GetEnd(scr, CHAR_CLOSE_BRACE, CHAR_OPEN_BRACE, TRUE);
- break;
- case CHAR_OPEN_PAREN:
- /* ...go to the corresponding parenthesis */
- ret=GetEnd(scr, CHAR_CLOSE_PAREN, CHAR_OPEN_PAREN, TRUE);
- break;
- case CHAR_QUOTATION_MARK:
- scr->text++;
- /* dirty use of function: */
- ret=GetEnd(scr, CHAR_QUOTATION_MARK, CHAR_QUOTATION_MARK, FALSE);
- break;
- case CHAR_ASCII_ZERO:
- if(Newline(scr))
- ret=FPLERR_INSIDE_NOT_FOUND;
- break;
- case CHAR_DIVIDE: /* to eat comments */
- case CHAR_SPACE:
- case CHAR_TAB:
- case CHAR_NEWLINE:
- if(Eat(scr))
- ret=FPLERR_INSIDE_NOT_FOUND;
- if(*scr->text==CHAR_HASH) {
- /* This should read a #line statement for new virtual line number */
- while(*scr->text++!=CHAR_NEWLINE);
- scr->virprg++;
- }
- break;
- case CHAR_CLOSE_BRACE: /* local function searches might hit this! */
- ret=FPLERR_INSIDE_NOT_FOUND;
- break;
- default:
- if(isident(*scr->text)) {
- Getword(scr);
- GetIdentifier(scr, scr->buf, &pident);
- if(pident && /* valid identifier */
- pident->data.external.ID==search) { /* and it's the right one */
- if(!Getword(scr)) {
- GetIdentifier(scr, scr->buf, &pident);
- if(pident && pident->flags&FPL_INSIDE_FUNCTION) /* an inside */
- cont=strcmp(pident->name, func->name); /* is it the right? */
- }
- } else
- while(isident(*scr->text))
- scr->text++;
- } else
- scr->text++;
- break;
- }
- }
- if(ret) {
- strcpy(scr->buf, func->name); /* enable better error report! */
- scr->prg=p;
- scr->text=t;
- scr->virprg=vp;
- return FPLERR_INSIDE_NOT_FOUND; /* dead end error */
- }
- func->data.inside.col=scr->text-(&scr->prog->program)[scr->prg-1];
- func->data.inside.prg=scr->prg;
- func->data.inside.virprg=scr->virprg;
- func->data.inside.virfile=scr->virfile;
- func->flags&=~FPL_INSIDE_NOTFOUND; /* we have found it! */
- } else {
- /*
- * We know where to find this function!
- */
-
- scr->prg=func->data.inside.prg;
- scr->text=(&scr->prog->program)[scr->prg-1]+func->data.inside.col;
- scr->virprg=func->data.inside.virprg;
- scr->virfile=func->data.inside.virfile;
- }
-
- /**********************************
- * PARSE THE PARAMETER LIST HERE! *
- **********************************/
-
- CALL(Eat(scr));
-
- if(*scr->text!=CHAR_OPEN_PAREN) {
- CALL(Warn(scr, FPLERR_MISSING_PARENTHESES));
- /* we can survive without that! */
- } else
- scr->text++;
-
- if(func->data.inside.format) {
- /*
- * We won't hit this if no arguments is prototyped.
- */
-
- count=0; /* parameter counter */
- text=func->data.inside.format;
-
- if(!*text) {
- if(!Getword(scr) && strcmp(scr->buf, "void")) {
- /* it should be "void" or nothing! If it wasn't we fail! */
- CALL(Warn(scr, FPLERR_ILLEGAL_DECLARE));
- }
- } else {
- while(*text && !ret) {
- CALL(Getword(scr));
- CALL(GetIdentifier(scr, scr->buf, &ident));
- CALL(Eat(scr));
- if(scr->text[0]==CHAR_MULTIPLY) {
- reference=TRUE;
- scr->text++; /* pass it! */
- }
- else
- reference=FALSE; /* no reference! */
-
- switch(*text) {
- case FPL_STRARG:
- case FPL_INTARG:
- if(reference) {
- /*
- * It was said to a symbol reference!!
- */
- CALL(Warn(scr, FPLERR_ILLEGAL_REFERENCE));
- }
- if(*text==FPL_STRARG &&
- ident->data.external.ID!=CMD_STRING) {
- CALL(Warn(scr, FPLERR_ILLEGAL_DECLARE));
- /* we create the variable that was declared in the prototype! */
- } else if(*text==FPL_INTARG &&
- ident->data.external.ID!=CMD_INT) {
- CALL(Warn(scr, FPLERR_ILLEGAL_DECLARE));
- /* we create the variable that was declared in the prototype! */
- }
- /*
- * Declare the following word as a string or integer
- * variable.
- */
- GETMEM(pident, sizeof(struct Identifier));
-
- CALL(Getword(scr));
-
- tempvar=&pident->data.variable;
-
- pident->flags=(*text==FPL_INTARG?FPL_INT_VARIABLE:
- FPL_STRING_VARIABLE)|
- (ident->flags&FPL_VARIABLE_LESS32);
-
- STRDUP(pident->name, scr->buf);
-
- tempvar->num=0; /* This is not an array */
- tempvar->size=1; /* This is not an array */
- GETMEM(tempvar->var.val32, sizeof(void *));
- if(*text==FPL_INTARG) {
- tempvar->var.val32[0]=(long)arg->argv[count];
- } else {
- /* Store string length in variable `len' */
- register long len=GETSTRLEN(arg->argv[count]);
- GETMEM(tempvar->var.str[0], sizeof(struct fplStr)+len);
- tempvar->var.str[0]->alloc=len;
-
- /* We copy the ending zero termination too! */
- memcpy(tempvar->var.str[0]->string, ((char *)arg->argv[count]), len+1);
- tempvar->var.str[0]->len=len;
- }
- /*
- * Emulate next level variable declaration by adding one
- * to the ->level member here... dirty but (fully?)
- * functional!!!! ;-)
- */
-
- pident->level=scr->varlevel+1;
- pident->file=scr->prog->name;
- pident->func=func;
- CALL(AddVar(scr, pident, &locals));
- break;
- case FPL_STRVARARG:
- case FPL_INTVARARG:
- case FPL_STRARRAYVARARG:
- case FPL_INTARRAYVARARG:
- if(!reference) {
- /*
- * It was never said to be a symbol reference!!
- */
- CALL(Warn(scr, FPLERR_ILLEGAL_REFERENCE));
- }
- if((*text==FPL_STRVARARG || *text == FPL_STRARRAYVARARG) &&
- ident->data.external.ID!=CMD_STRING) {
- CALL(Warn(scr, FPLERR_ILLEGAL_DECLARE));
- /* create a string reference anyway! */
- } else if((*text==FPL_INTVARARG || *text == FPL_INTARRAYVARARG) &&
- ident->data.external.ID!=CMD_INT) {
- CALL(Warn(scr, FPLERR_ILLEGAL_DECLARE));
- /* create an int reference anyway! */
- }
- /*
- * Declare the following word as a variable which
- * will use the struct fplVariable pointer as given in the
- * calling parameter list.
- */
-
- CALL(Getword(scr));
-
- if(*text == FPL_INTARRAYVARARG ||
- *text == FPL_STRARRAYVARARG) {
- CALL(Eat(scr));
- if(CHAR_OPEN_BRACKET != scr->text[0])
- return FPLERR_ILLEGAL_DECLARE;
- if(GetEnd(scr, CHAR_CLOSE_BRACKET, CHAR_OPEN_BRACKET, FALSE))
- return FPLERR_MISSING_BRACKET;
- }
-
- if(arg->argv[count]) {
- /*
- * If the wrong kind of variable was sent in the function call, no
- * varible will be sent, and no one will be declared.
- */
-
- GETMEM(pident, sizeof(struct Identifier));
-
- *pident=*(struct Identifier *)arg->argv[count];
- pident->flags |= FPL_REFERENCE;
- pident->data.variable.ref= (struct Identifier *)arg->argv[count];
- /* original fplVariable position */
-
- STRDUP(pident->name, scr->buf);
-
- pident->level=scr->varlevel+1;
- pident->file=scr->prog->name;
- pident->func=func;
- CALL(AddVar(scr, pident, &locals));
- }
- break;
- }
- CALL(Eat(scr));
-
- if(*++text && *scr->text++!=CHAR_COMMA)
- /*
- * There is no way out from this error exception. Leaving a parameter
- * really is a sever thing!
- */
- return(FPLERR_MISSING_ARGUMENT);
- count++;
- }
- }
-
- CALL(Eat(scr));
-
- if(*scr->text!=CHAR_CLOSE_PAREN) {
- CALL(Warn(scr, FPLERR_MISSING_PARENTHESES));
- /* who needs ending parentheses? */
- } else
- scr->text++;
- } else {
- /*
- * No argument is useable to this function. There might be a
- * `void' keyword here, but nothing else! Just search for the
- * closing parenthesis to fasten interpreting!
- */
-
- if(ret=GetEnd(scr, CHAR_CLOSE_PAREN, CHAR_OPEN_PAREN, FALSE)) {
- CALL(Warn(scr, FPLERR_MISSING_PARENTHESES));
- /* ok, then search for the open brace where the program starts! */
- ret=GetEnd(scr, CHAR_OPEN_BRACE, CHAR_OPEN_PAREN, FALSE);
- if(ret) {
- CALL(Warn(scr, FPLERR_MISSING_BRACE));
- } else
- scr->text--; /* back on brace */
- /* ok, then we say that the program starts right here! */
- }
- }
-
- /*********************
- * RUN THE FUNCTION! *
- *********************/
-
- oldret=scr->strret;
- scr->strret=func->data.inside.ret==FPL_STRARG; /* should we receive a string? */
- CALL(Eat(scr));
- if(*scr->text!=CHAR_OPEN_BRACE) {
- CALL(Warn(scr, FPLERR_MISSING_BRACE));
- /* we can do with a start without it! */
- } else
- scr->text++;
-
- con.bracetext=scr->text;
- con.braceprg=scr->prg;
- text=(void *)scr->func; /* backup current */
- scr->func=func;
-
- scr->prog->openings++;
- ret=Script(scr, val, SCR_BRACE|SCR_FUNCTION, &con);
- scr->prog->openings--;
-
- /*
- * Delete all variables created on our list for use
- * only in the function we just came back from!
- */
- DelLocalVar(scr, &locals);
-
- if(ret) {
- if(scr->prog != prog) {
- LeaveProgram(scr, scr->prog); /* leave the failed program! */
- GetProgram(scr, prog); /* fetch the previous program again! */
- }
- return(ret);
- }
- scr->func=(void *)text; /* restore last */
-
- if(scr->strret) {
- /* we should return a string */
- string=val->val.str;
-
- strtags[1]=(long)string->string;
- strtags[3]=string->len;
- CALL(Send(scr, strtags));
- FREE(string);
- } else {
- inttags[1]=val->val.val;
- CALL(Send(scr, inttags));
- }
-
- FREE(val);
-
- scr->text=t;
- scr->prg=p;
- scr->virprg=vp;
- scr->virfile=vf;
- scr->strret=oldret;
- if(scr->prog!=prog) {
- CALL(LeaveProgram(scr, scr->prog));
- scr->prog=prog;
- CALL(GetProgram(scr, scr->prog));
- }
- return(FPL_OK);
- }
-
- static ReturnCode INLINE PrototypeInside(struct Data *scr,
- struct Expr *val,
- long control,
- struct Identifier *ident)
- {
- /*
- * Prototyping an `inside' function!
- *
- * We have already received the return type, now we must
- * parse the paraters given within the parentheses. Legal
- * parameters are only combinations of `string', `int',
- * `string &' and `int &', or a single `void' (if no argument
- * should be sent to the function). Arguments specified in
- * a prototype is required, there is no way to specify an
- * optional parameter or a parameter list.
- */
-
- struct Identifier *pident;
- long pos=0;
- ReturnCode ret = FPL_OK;
- char *array;
- char found=ident?TRUE:FALSE;
-
- if(!found) {
- GETMEM(pident, sizeof(struct Identifier));
- STRDUP(pident->name, scr->buf);
- } else {
- /* we already know about this function! */
- if(ident->flags&(FPL_INTERNAL_FUNCTION|FPL_KEYWORD|FPL_EXTERNAL_FUNCTION))
- return FPLERR_IDENTIFIER_USED;
- pident = ident;
- }
-
- if(!found || (found && ident->flags&FPL_INSIDE_NOTFOUND)) {
- /* we know where this is... */
- pident->data.inside.col=scr->text-(&scr->prog->program)[scr->prg-1];
- pident->data.inside.prg=scr->prg;
- pident->data.inside.file=scr->prog->name;
- pident->data.inside.virprg=scr->virprg;
- pident->data.inside.virfile=scr->virfile;
-
- pident->file=scr->prog->name; /* file! */
- pident->func=scr->func; /* declared in this function */
- pident->level=control&CON_DECLGLOB?0:scr->varlevel;
- }
-
- if(found) {
- /* we already know about this function! */
-
- CALL(GetEnd(scr, CHAR_CLOSE_PAREN, CHAR_OPEN_PAREN, TRUE));
-
- CALL(Eat(scr));
-
- if(scr->text[0]==CHAR_OPEN_BRACE) {
- /* now the function is found! */
- if(!(ident->flags&FPL_INSIDE_NOTFOUND))
- /* the function has already been defined and is defined here again! */
- return FPLERR_IDENTIFIER_USED;
-
- ident->flags&=~FPL_INSIDE_NOTFOUND;
-
- if(GetEnd(scr, CHAR_CLOSE_BRACE, CHAR_OPEN_BRACE, TRUE))
- return FPLERR_MISSING_BRACE;
- scr->text--; /* back on close brace */
- val->flags|=FPL_DEFUNCTION;
- }
-
- return FPL_OK;
- }
-
- pident->flags=FPL_INSIDE_FUNCTION|
- (control&CON_DECLEXP?FPL_EXPORT_SYMBOL:0)|
- (control&CON_DECLGLOB?FPL_GLOBAL_SYMBOL:0);
-
- scr->text++; /* pass the open parenthesis */
-
- CALL(Eat(scr));
-
- GETMEM(array, MAX_ARGUMENTS * sizeof(char));
-
- while(pos<MAX_ARGUMENTS) {
- if(*scr->text==CHAR_CLOSE_PAREN) {
- scr->text++;
- break;
- }
- CALL(Getword(scr));
- CALL(GetIdentifier(scr, scr->buf, &ident));
- CALL(Eat(scr));
- switch(ident->data.external.ID) {
- case CMD_VOID:
- if(*scr->text!=CHAR_CLOSE_PAREN) {
- CALL(Warn(scr, FPLERR_ILLEGAL_PROTOTYPE));
- CALL(GetEnd(scr, CHAR_CLOSE_PAREN, CHAR_OPEN_PAREN, TRUE));
- } else
- scr->text++;
- break;
-
- case CMD_STRING:
- case CMD_INT:
- if(*scr->text==CHAR_MULTIPLY) {
- scr->text++;
- Getword(scr); /* eat word if there's any! */
- if(CHAR_OPEN_BRACKET == scr->text[0]) {
- if(GetEnd(scr, CHAR_CLOSE_BRACKET, CHAR_OPEN_BRACKET, FALSE))
- return FPLERR_MISSING_BRACKET;
- array[pos]=(ident->data.external.ID==CMD_STRING)?FPL_STRARRAYVARARG:
- FPL_INTARRAYVARARG;
- }
- else
- array[pos]=(ident->data.external.ID==CMD_STRING)?FPL_STRVARARG:
- FPL_INTVARARG;
- } else
- array[pos]=(ident->data.external.ID==CMD_STRING)?FPL_STRARG:
- FPL_INTARG;
- break;
-
- default:
- CALL(Warn(scr, FPLERR_ILLEGAL_PROTOTYPE));
- continue; /* if we against all odds are ordered to go on! */
- }
- if(CMD_VOID == ident->data.external.ID)
- break;
-
- pos++;
- if(isident(*scr->text)) {
- Getword(scr);
- CALL(Eat(scr));
- }
-
- if(*scr->text==CHAR_COMMA)
- scr->text++;
- else if(*scr->text!=CHAR_CLOSE_PAREN) {
- CALL(Warn(scr, FPLERR_ILLEGAL_PROTOTYPE));
- /* we can go on if we just forgot the closing parenthesis */
- }
- }
-
- array[pos]=0; /* terminate string */
-
- /*
- * We have all information now. AddIdentifier().
- */
-
- pident->data.inside.ret=(control&CON_DECLSTR)?FPL_STRARG:
- (control&CON_DECLINT)?FPL_INTARG:FPL_VOIDARG;
- GETMEM(pident->data.inside.format, pos+1);
- strcpy(pident->data.inside.format, array);
- FREE(array);
-
- CALL(Eat(scr)); /* Eat white space */
-
-
- if(*scr->text==CHAR_OPEN_BRACE) {
- /* It's the actual function!!! */
- if(GetEnd(scr, CHAR_CLOSE_BRACE, CHAR_OPEN_BRACE, TRUE))
- return FPLERR_MISSING_BRACE;
- scr->text--; /* back on close brace */
- val->flags|=FPL_DEFUNCTION;
- } else {
- val->flags&=~FPL_DEFUNCTION;
- pident->flags|=FPL_INSIDE_NOTFOUND;
- }
- CALL(AddVar(scr, pident,
- control&CON_DECLGLOB?&scr->globals:&scr->locals));
-
- return(ret);
- }
-